package com.yc.rpc.core.server;

import com.yc.rpc.core.RpcClientConfig;
import com.yc.rpc.core.RpcServerConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Objects;


@Component
public class NettyServer implements ApplicationContextAware, InitializingBean {

    private static final Logger logger = LoggerFactory.getLogger(NettyServer.class);
    private static final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    private static final EventLoopGroup workerGroup = new NioEventLoopGroup(4);

    private ApplicationContext context;

    @Autowired
    private RpcServerConfig rpcServerConfig;

    @Value("${rpc.hundun.server}")
    private String rpcHunServer;

    public void start(){
        final NettyServerHandler handler = new NettyServerHandler(context);
        new Thread(() -> {
            try {
                ServerBootstrap bootstrap = new ServerBootstrap();
                bootstrap.group(bossGroup,workerGroup).
                        channel(NioServerSocketChannel.class).
                        option(ChannelOption.SO_BACKLOG,1024).
                        childOption(ChannelOption.SO_KEEPALIVE,true).
                        childOption(ChannelOption.TCP_NODELAY,true).
                        childHandler(new ChannelInitializer<SocketChannel>() {
                            //创建NIOSocketChannel成功后，在进行初始化时，将它的ChannelHandler设置到ChannelPipeline中，用于处理网络IO事件
                            @Override
                            protected void initChannel(SocketChannel channel) {
                                ChannelPipeline pipeline = channel.pipeline();
//                                pipeline.addLast(new IdleStateHandler(0, 0, 60));
//                                pipeline.addLast(new StringDecoder());
                                pipeline.addLast(new LineBasedFrameDecoder(Integer.MAX_VALUE));
//                                pipeline.addLast(new StringEncoder());
                                pipeline.addLast(handler);
                            }
                        });

                String host = rpcServerConfig.getHost();
                int port = rpcServerConfig.getPort();
                ChannelFuture cf = bootstrap.bind(host,port).sync();
                logger.info("RPC 服务器启动.监听端口:"+port);
//                registry.register(serverAddress);
                //等待服务端监听端口关闭
                cf.channel().closeFuture().sync();



            } catch (Exception e) {
                e.printStackTrace();
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }).start();
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        start();
        final String[] servers = rpcHunServer.split(",");
        final String[] split = servers[0].split(":");
        new HundunClient(rpcServerConfig).connect(split[0], Integer.valueOf(split[1]));
    }
}
